Skip to content

[typescript-fetch] centralise date handling, add dateLibrary - #24722

Merged
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library
Aug 17, 2026
Merged

[typescript-fetch] centralise date handling, add dateLibrary#24722
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library

Conversation

@wing328

@wing328 wing328 commented Aug 17, 2026

Copy link
Copy Markdown
Member

based on #24637 with updated samples.

all TS tests passed.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Centralizes date handling for typescript-fetch and adds a dateLibrary option to choose Date (default) or string. Fixes format: date bugs (incorrect form param serialization and UTC day shifts) by using the local calendar for date and UTC for date-time.

  • Runtime: all date parsing/serialization now uses parseDate, parseDateTime, serializeDate, and serializeDateTime in runtime.ts; querystring and path/query/form params route through these.
  • Generator: new additionalProperties.dateLibrary option (date | string); withoutRuntimeChecks implies string. Docs updated.
  • Templates: models and oneOf guards align with helpers; date imports only when needed via x-hasDateVars. ES6-safe code; preserves years 0000–0099 and rejects invalid dates.
  • Tests/samples: added a fixture covering all date locations and two sample builds (date and string).

Migration

  • If your client expects string dates, set -p dateLibrary=string (or dateLibrary: string in config). Regenerate and update types accordingly.
  • If you relied on withoutRuntimeChecks for string dates, no change; to get Date, disable that flag and/or set -p dateLibrary=date.

Written for commit b71f03e. Summary will update on new commits.

Review in cubic

b2l and others added 7 commits August 12, 2026 09:48
…mat: date

Date handling was spread across four templates, each inlining its own
expression. That had three consequences:

1. `format: date` was not handled at all for form parameters, so a Date
   was appended raw and stringified by the browser
   ("Wed Aug 05 2026 00:00:00 GMT+0200 (…)") instead of "2026-08-05".

2. `format: date` shifted by a day everywhere except UTC, in one direction
   or the other. Parsing (`new Date('2026-08-05')`) and serialising
   (`.toISOString().substring(0, 10)`) both work in UTC, but consumers do
   not: a date picker builds local midnight and display reads local
   getters. West of UTC a date from the API displays as the previous day;
   east of UTC a locally built date is sent as the previous day. An RFC
   3339 full-date has no offset, so both ends have to use the same wall
   clock — they now both use the local calendar. `format: date-time` is a
   genuine instant and stays UTC.

3. Whether dates were represented as Date or string was decided by
   `withoutRuntimeChecks`, an unrelated flag about payload validation.

All call sites (models, oneOf models, path/query/form parameters and the
querystring helper) now route through serializeDate/serializeDateTime and
parseDate/parseDateTime in runtime.ts, so the representation is defined in
one place. The new `dateLibrary` option (`date`, the default and previous
behaviour, or `string`) makes the choice explicit; `withoutRuntimeChecks`
implies `string`, as before, since there is no model code left to convert
with.

Adds a spec fixture covering every location a date can appear in, two
sample builds (one per option value), and tests for the option, the
fallback and the serialisation semantics.
…es, unused imports

- serializeDate no longer uses padStart, which is ES2017: the es6-target
  sample did not compile against its own tsconfig.
- parseDate builds the local date with setFullYear, so years 0000-0099 keep
  their century instead of picking up the multi-argument Date constructor's
  1900 offset ("0045-08-05" was parsed as 1945).
- parseDate rejects components that roll over, so an out-of-range date or a
  day the local zone skipped returns Invalid Date rather than a plausible
  wrong one. Previously "2026-13-45" became 2027-02-14.
- serializeDate throws RangeError on an invalid Date instead of emitting
  "0NaN-NaN-NaN", matching serializeDateTime.
- Models without a date property no longer import the date helpers, via a
  new x-hasDateVars extension mirroring the template's own branches. This
  reverts most of the sample churn from the previous commit.

Drops testDateFormatUsesTheLocalCalendar: runtime.ts is identical for every
spec, so asserting its body only restated the template. The per-build
tsconfig typecheck covers the ES6 regression properly.
The oneOf branches tested a value with `new Date(json)` but converted it with
parseDate, so the two could disagree: "2026-02-30" passes the lenient test (V8
rolls it to March 2) and then parseDate rejects it, leaving the branch selected
and returning Invalid Date. Testing with the same helper that does the
conversion lets the oneOf fall through to another branch instead.

Adds a oneOf date member to the date-handling fixture. No sample in the repo
exercised these branches, so the generated form of the guard was invisible in
the samples; only the scalar variant is left out, because a scalar oneOf
primitive already fails `tsc --strict` on master (it can return undefined,
which is not in the union).

Drops the comment justifying the ES6-safe padding: the per-build tsconfig
typecheck already fails if someone reaches for padStart again.
… the date helpers

Upstream #24509 null-guarded required date properties; keep that guard
but route the conversion through parseDate/serializeDate. Port the form
param date handling into the apisFormParams partial extracted by #23935,
and regenerate the affected samples.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…runtime.mustache

Co-authored-by: Esteban Gehring <esteban.gehring@gmail.com>
@wing328 wing328 added Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc. labels Aug 17, 2026
@wing328 wing328 added this to the 7.25.0 milestone Aug 17, 2026
@wing328 wing328 changed the title Le comptoir des pharmacies feat/typescript fetch date library [typescript-fetch] centralise date handling, add dateLibrary Aug 17, 2026
@wing328
wing328 marked this pull request as ready for review August 17, 2026 09:27
@wing328
wing328 merged commit 51433f0 into master Aug 17, 2026
245 of 477 checks passed
@wing328
wing328 deleted the LeComptoirDesPharmacies-feat/typescript-fetch-date-library branch August 17, 2026 09:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants